#include "SDLTextBox.h"

Uint32 (*pToggleCaret)(Uint32 interval, void *oTextBox) = &_toggleCaret;

SDLTextBox::SDLTextBox() :
screen(NULL),
font(NULL),
event(NULL),
max_len(0),
lines(1),
pClipboard(NULL)
{
	textBoxBody = 0;
	textColor.r = 0xFF;
	textColor.g = 0xFF;
	textColor.b = 0x00;
	SDL_EnableUNICODE(SDL_ENABLE);
	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 15);
	caretTimer = SDL_AddTimer(500, pToggleCaret, this);
	caret.caretOn = true;
	caret.caretOff = false;
	caret.caretLoc = 0;
	caret.caretX = 0;
	caret.caretY = 0;
	caret.caretH = 0;
	highlight.active = false;
	highlight.start = 0;
	highlight.stop = 0;
	normalCursor = SDL_GetCursor();
	textCursor = SDL_MakeCursor(textCursorBMP);
	vector <pair <string, bool> > popupMenuInit;
	string label1 = "Cut";
	string label2 = "Copy";
	string label3 = "Paste";
	string label4 = "Select All";
	string label5 = "Delete";
	popupMenuInit.push_back(make_pair(label1, false));
	popupMenuInit.push_back(make_pair(label2, false));
	popupMenuInit.push_back(make_pair(label3, false));
	popupMenuInit.push_back(make_pair(label4, false));
	popupMenuInit.push_back(make_pair(label5, false));
	SDL_Color popupNormal = {0xFF, 0xFF, 0x00};
	SDL_Color popupGrayed = {0x77, 0x77, 0x22};
	pPopupMenu = new SDLPopupMenu(popupMenuInit, popupNormal, popupGrayed, screen, event, font, this);
	setFocus(false);
}

SDLTextBox::SDLTextBox(SDL_Surface *_screen, TTF_Font *_font, SDL_Color _textColor, SDL_Event *_event, SDLClipboard *_pClipboard, const char *bgFileName, int _max_len) :
screen(_screen),
font(_font),
event(_event),
max_len(_max_len),
textColor(_textColor),
lines(1),
pClipboard(_pClipboard)
{
	if(bgFileName) textBoxBody = load_image(bgFileName);
	else textBoxBody = 0;
	SDL_EnableUNICODE(SDL_ENABLE);
	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
	caretTimer = SDL_AddTimer(500, pToggleCaret, this);
	caret.caretOn = true;
	caret.caretOff = false;
	caret.caretLoc = 0;
	caret.caretX = 0;
	caret.caretY = 0;
	caret.caretH = 0;
	box.x = 40;
	box.y = 40;
	box.w = 400;
	box.h = 0;
	highlight.active = false;
	highlight.start = 0;
	highlight.stop = 0;
	normalCursor = SDL_GetCursor();
	textCursor = SDL_MakeCursor(textCursorBMP);
	vector <pair <string, bool> > popupMenuInit;
	string label1 = "Cut";
	string label2 = "Copy";
	string label3 = "Paste";
	string label4 = "Select All";
	string label5 = "Delete";
	popupMenuInit.push_back(make_pair(label1, false));
	popupMenuInit.push_back(make_pair(label2, false));
	popupMenuInit.push_back(make_pair(label3, false));
	popupMenuInit.push_back(make_pair(label4, false));
	popupMenuInit.push_back(make_pair(label5, false));
	SDL_Color popupNormal = {0xFF, 0xFF, 0x00};
	SDL_Color popupGrayed = {0x77, 0x77, 0x22};
	pPopupMenu = new SDLPopupMenu(popupMenuInit, popupNormal, popupGrayed, screen, event, font, this);
	setFocus(false);
}

SDLTextBox::~SDLTextBox() {
	if(textBoxBody) SDL_FreeSurface(textBoxBody);
	if(normalCursor) SDL_FreeCursor(normalCursor);
	if(textCursor) SDL_FreeCursor(textCursor);
	SDL_EnableUNICODE(SDL_DISABLE);
}

void SDLTextBox::inputHandler() {
	//if(event->type == SDL_MOUSEBUTTONDOWN) setFocus(true);
	if(hasFocus()) {
		int x, y;
		int caretLocBuffer = 0;
		string temp;
		if(highlight.start != highlight.stop) { 
			pPopupMenu->setActive(POPUP_CUT, true);
			pPopupMenu->setActive(POPUP_COPY, true);
			pPopupMenu->setActive(POPUP_DELETE, true);
		} else {
			pPopupMenu->setActive(POPUP_CUT, false);
			pPopupMenu->setActive(POPUP_COPY, false);
			pPopupMenu->setActive(POPUP_DELETE, false);
		}
		if(str.size() > 0) {
			pPopupMenu->setActive(POPUP_SELECTALL, true);
		} else {
			pPopupMenu->setActive(POPUP_SELECTALL, false);
		}
		if(&pClipboard->getData() != NULL) {
			pPopupMenu->setActive(POPUP_PASTE, true);
		} else {
			pPopupMenu->setActive(POPUP_PASTE, false);
		}
		if(pPopupMenu->isVisible()) {
			SDL_SetCursor(normalCursor);
			pPopupMenu->inputHandler();
		} else {
			switch(event->type) {
			case SDL_KEYDOWN:
				switch(event->key.keysym.sym) {
				case SDLK_BACKSPACE:
					if(str.length() != 0 && caret.caretLoc > 0) {
						if(highlight.start != highlight.stop) {
							if(highlight.start > highlight.stop) {
								x = highlight.stop;
								y = highlight.start;
							} else {
								x = highlight.start;
								y = highlight.stop;
							}
							str.erase(x, y - x);
							caret.caretLoc = x;
							highlight.start = 0;
							highlight.stop = 0;
						} else {
							str.erase(caret.caretLoc - 1, 1);
							caret.caretLoc--;
						}
					}
					break;
				case SDLK_DELETE:
					if(caret.caretLoc < str.size()) {
						if(highlight.start != highlight.stop) {
							if(highlight.start > highlight.stop) {
								x = highlight.stop;
								y = highlight.start;
							} else {
								x = highlight.start;
								y = highlight.stop;
							}
							str.erase(x, y - x);
							caret.caretLoc = x;
							highlight.start = 0;
							highlight.stop = 0;
						} else str.erase(caret.caretLoc, 1);
					}
					break;
				case SDLK_HOME:
					caret.caretLoc = 0;
					break;
				case SDLK_END:
					caret.caretLoc = str.size();
					break;
				default:
					//left, right, up, down have to be in default so that ctrl-dir will work for highlighting.
					if(event->key.keysym.sym == SDLK_LEFT) if(caret.caretLoc > 0) caret.caretLoc--;
					if(event->key.keysym.sym == SDLK_RIGHT) if(caret.caretLoc < str.length()) caret.caretLoc++;
					if(event->key.keysym.sym == SDLK_UP) {
						if(findCharXY(caret.caretX, caret.caretY - caret.caretH / 2) > 0) caret.caretLoc = findCharXY(caret.caretX, caret.caretY - caret.caretH / 2);
						else caret.caretLoc = 0;
					}
					if(event->key.keysym.sym == SDLK_DOWN) {
						if(findCharXY(caret.caretX, caret.caretY + (caret.caretH + caret.caretH / 2)) > 0) caret.caretLoc = findCharXY(caret.caretX, caret.caretY + (caret.caretH + caret.caretH / 2));
						else caret.caretLoc = str.size();
					}

					if(str.length() <= max_len) {
						if(event->key.keysym.unicode >= 0x20 && event->key.keysym.unicode <= 0x7E) {
							temp = (char)event->key.keysym.unicode;
							str.insert(caret.caretLoc, temp);
							caret.caretLoc++;
						}
					}
					if(event->key.keysym.mod & KMOD_CTRL) {
						switch(event->key.keysym.sym) {
						case 'a':
							highlight.start = 1; //should be 0, fix when I go through and make 0 an acceptable index for highlighting
							highlight.stop = str.size();
							highlight.active = true;
							break;
						case 'c':
							if(highlight.start != highlight.stop) {
								if(highlight.start > highlight.stop) {
									x = highlight.stop;
									y = highlight.start;
								} else {
									x = highlight.start;
									y = highlight.stop;
								}
								if(str.substr(x, y - x).size() > 0) pClipboard->setData(str.substr(x, y - x));
							}
							break;
						case 'v':
							if(pClipboard->getData().size() > 0) {
								if(highlight.start == highlight.stop) {
									temp = pClipboard->getData();
									if(temp.size() > 0) {
										if(str.size() + temp.size() > max_len) {
											x = max_len - str.size();
											temp.erase(x, temp.size() - x);
										}
										str.insert(caret.caretLoc, temp);
										caret.caretLoc += temp.size();
									}
								} else {
									if(highlight.start > highlight.stop) {
										x = highlight.stop;
										y = highlight.start;
									} else {
										x = highlight.start;
										y = highlight.stop;
									}
									temp = str.substr(x, y - x);
									str.erase(x, y - x);
									caret.caretLoc = y;
									caret.caretLoc -= temp.size();
									temp = pClipboard->getData();
									if(str.size() + temp.size() > max_len) {
										x = max_len - str.size();
										temp.erase(x, temp.size() - x);
									}
									str.insert(caret.caretLoc, temp);
									highlight.start = 0;
									highlight.stop = 0;
									caret.caretLoc += temp.size();
								}
							}
							break;
						case 'x':
							if(highlight.start != highlight.stop) {
								if(highlight.start > highlight.stop) {
									x = highlight.stop;
									y = highlight.start;
								} else {
									x = highlight.start;
									y = highlight.stop;
								}
								if(str.substr(x, y - x).size() > 0) pClipboard->setData(str.substr(x, y - x));
								str.erase(x, y - x);
								caret.caretLoc = x;
								highlight.start = 0;
								highlight.stop = 0;
							}
							break;
						case SDLK_LEFT:
							if(highlight.active) {
								if(highlight.stop == caret.caretLoc + 1) {
									highlight.stop = caret.caretLoc;
								} else {
									highlight.start = caret.caretLoc + 1;
									highlight.stop = caret.caretLoc;
								}
							} else {
								highlight.start = caret.caretLoc + 1;
								highlight.stop = caret.caretLoc;
								highlight.active = true;
							}
							break;
						case SDLK_RIGHT:
							if(highlight.active) {
								if(highlight.stop == caret.caretLoc - 1) {
									highlight.stop = caret.caretLoc;
								} else {
									highlight.start = caret.caretLoc - 1;
									highlight.stop = caret.caretLoc;
								}
							} else {
								highlight.start = caret.caretLoc - 1;
								highlight.stop = caret.caretLoc;
								highlight.active = true;
							}
							break;
						case SDLK_UP:		//not too sure why up and down work the same here..
						case SDLK_DOWN:
							x = findCharXY(caret.caretX, caret.caretY + caret.caretH / 2);
							if(highlight.active) {
								if(highlight.stop == x - 1 || highlight.stop == x + 1 || highlight.stop == x) {
									highlight.stop = caret.caretLoc;
								} else {
									highlight.start = x;
									highlight.stop = caret.caretLoc;
								}
							} else {
								highlight.start = x;
								highlight.stop = caret.caretLoc;
								highlight.active = true;
							}
							break;
						case 'k':
							str.erase();
							caret.caretLoc = 0;
							highlight.active = false;
							highlight.start = 0;
							highlight.stop = 0;
							break;
						}
					}
				}
				break;
			case SDL_MOUSEBUTTONDOWN:
				switch(event->button.button) {
				case SDL_BUTTON_LEFT:
					x = event->button.x;
					y = event->button.y;
					if((x > box.x) && (x < box.x + box.w) && (y > box.y) && (y < box.y + box.h)) {
						caretLocBuffer = findCharXY(x, y);
						if(caretLocBuffer) {
							caret.caretLoc = caretLocBuffer;
							if(!highlight.active) {
								highlight.start = 0;
								highlight.stop = 0;
								highlight.start = caretLocBuffer;
								highlight.active = true;
							}
						}
						if(pPopupMenu->isVisible()) pPopupMenu->hide();
					}
					break;
				case SDL_BUTTON_RIGHT:
					x = event->button.x;
					y = event->button.y;
					if((x > box.x) && (x < box.x + box.w) && (y > box.y) && (y < box.y + box.h)) {
						mousePos.x = x;
						mousePos.y = y;
						if(pPopupMenu->mustRender()) pPopupMenu->render();
						pPopupMenu->show(mousePos.x, mousePos.y);
					}
					break;
				}
				break;
			case SDL_MOUSEMOTION:
				x = event->motion.x;
				y = event->motion.y;
				if((x > box.x) && (x < box.x + box.w) && (y > box.y) && (y < box.y + box.h)) {
					SDL_SetCursor(textCursor);
				} else {
					SDL_SetCursor(normalCursor);
				}
				if(event->motion.state & SDL_BUTTON(1)) {
					if((x > box.x) && (x < box.x + box.w) && (y > box.y) && (y < box.y + box.h)) {
						if(!highlight.active) {
							highlight.start = 0;
							highlight.stop = 0;
							caretLocBuffer = findCharXY(x, y);
							if(caretLocBuffer) highlight.start = caretLocBuffer;
							highlight.active = true;
						} else if(highlight.active) {
							caretLocBuffer = findCharXY(x, y);
							if(caretLocBuffer) highlight.stop = caretLocBuffer;
							caret.caretLoc = caretLocBuffer;
						}
					}
				}
				break;
			case SDL_MOUSEBUTTONUP:
				if(event->button.button == SDL_BUTTON_LEFT) {
					x = event->button.x;
					y = event->button.y;
					if(highlight.active) {
						caretLocBuffer = findCharXY(x, y);
						if(caretLocBuffer) highlight.stop = caretLocBuffer;
						highlight.active = false;
					} else {
						highlight.start = 0;
						highlight.stop = 0;
					}
				}
				break;
			default:
				//unknown event
				break;
			}
		}
	}
}


void SDLTextBox::display() {
	int w = 0, h = 0, i = 0;
	int last = 0;
	bool caretDrawn = false;
	if(str.size() > 0) {
		SDL_Surface *apply = 0;
		vector <SDL_Surface *> buffer;
		lines = makeLines(box.w);
		for(i = 0; i < vLines.size(); i++) {
			apply = TTF_RenderText_Solid(font, vLines[i].c_str(), textColor);
			box.h = lines * apply->h;
			if(textBoxBody) apply_surface(box.x, box.y + (i * apply->h), textBoxBody, screen);
			apply_surface(box.x, box.y + (i * apply->h), apply, screen);
			if(textBoxBody) {
				buffer.push_back(apply);
				buffer[i]->refcount++;
				for(int k = 0; k < i; k++) apply_surface(box.x, box.y + (k * buffer[k]->h), buffer[k], screen);
			}
			SDL_FreeSurface(apply);
		}
		if(textBoxBody) {
			for(i = 0; i < buffer.size(); i++) SDL_FreeSurface(buffer[i]);
			buffer.clear();
		}
	}
	if(caret.caretOn) {
	int w2 = 0;
		for(i = 0; i < vLines.size(); i++) {
			if(caret.caretLoc <= vLines[i].size() + last && !caretDrawn) {
				TTF_SizeText(font, vLines[i].substr(0, caret.caretLoc - last).c_str(), &w, &h);
				caret.caretX = box.x + w;
				caret.caretY = box.y + (i * h);
				caret.caretH = h;
				draw_line(screen, caret.caretX, caret.caretY, caret.caretH, 0xffff00);
				caretDrawn = true;
			}
			last += vLines[i].size();
		}
		caret.caretOn = false;
		caret.caretOff = true;
	}
	if(caret.debugX && caret.debugY) {
		draw_line(screen, caret.debugX, caret.debugY, 2, 0xff0000);
		draw_line(screen, caret.debugX + 1, caret.debugY, 2, 0x0ff000);
	}
	doHighlight();
	if(pPopupMenu->isVisible()) {
		if(pPopupMenu->mustRender()) pPopupMenu->render();
		pPopupMenu->show(mousePos.x, mousePos.y);
		pPopupMenu->doHighlight(pPopupMenu->getCurrentItem());
	}
	
	/*int w = 0, h = 0;
	if(str.size() > 0) {
		SDL_Surface *apply = 0;
		vector <SDL_Surface *> buffer;
		lines = makeLines(615);
		for(int i = 0; i < vLines.size(); i++) {
			apply = TTF_RenderText_Solid(font, vLines[i].c_str(), textColor);
			if(textBoxBody) apply_surface(0, (SCREEN_HEIGHT - (apply->h * (i + 1) + 5)), textBoxBody, screen);
			apply_surface(5, (SCREEN_HEIGHT - (apply->h * ((lines - (i + 1)) + 1))), apply, screen);
			buffer.push_back(apply);
			buffer[i]->refcount++;
			for(int k = 0; k < i; k++) apply_surface(5, (SCREEN_HEIGHT - (buffer[i]->h * (lines - k))), buffer[k], screen);
			SDL_FreeSurface(apply);
		}
		for(i = 0; i < buffer.size(); i++) SDL_FreeSurface(buffer[i]);
		buffer.clear();
	}
	int last = 0;
	bool caretDrawn = false;
	if(caret.caretOn) {
	int w2 = 0;
		for(int i = 0; i < vLines.size(); i++) {
			if(caret.caretLoc <= vLines[i].size() + last && !caretDrawn) {
				TTF_SizeText(font, vLines[i].substr(0, caret.caretLoc - last).c_str(), &w, &h);
				caret.caretX = (5 + w);
				caret.caretY = (SCREEN_HEIGHT - (h * (vLines.size() - i)));
				caret.caretH = h;
				draw_line(screen, caret.caretX, caret.caretY, caret.caretH, 0xffff00);
				caretDrawn = true;
			}
			last += vLines[i].size();
		}
		caret.caretOn = false;
		caret.caretOff = true;
	}*/
}

Uint32 SDLTextBox::toggleCaret(Uint32 interval, void *param) {
	if(caret.caretOff) {
		caret.caretOn = true;
		caret.caretOff = false;
	}
	return interval;
}

int SDLTextBox::makeLines(int width) {
	string buffer = str;
	vLines.clear();
	bool hack = false;
	int w = 0, h = 0, i = 1;
	int i2;
	if(str.size() <= 0) return 0;
	do {
		if(hack) {
			vLines.pop_back();
			hack = false;
		}
		i = 1;
		do {
			TTF_SizeText(font, buffer.substr(0, i++).c_str(), &w, &h); 
		} while(w <= width && i < buffer.size());
		if(i > 0) {
			i2 = i;
			if(w >= width) {
				do { 
					i--;
				} while(buffer.substr(0, i).c_str()[buffer.substr(0, i).size() - 1] != ' ' && i >= 0);
				if(i > 0) {
					vLines.push_back(buffer.substr(0, i));
					vLines.push_back(buffer.substr(i, i2));
					buffer.erase(0, i);
					hack = true;
				} else {
					i = i2;
					i--;
					vLines.push_back(buffer.substr(0, i));
					buffer.erase(0, i);
					i = 1;
					vLines.push_back(buffer.substr(0, 1));
					hack = true;
				}
			} else  {
				vLines.push_back(buffer.substr(0, i));
				buffer.erase(0, i);
			}
		}
	} while(i < buffer.size());
	return vLines.size();
}

int SDLTextBox::findCharXY(int x, int y) {
	caret.debugX = x;
	caret.debugY = y;
	string buffer = str;
	int w = 0, h = 0, i = 0, j = 1, last = 0;
	for(i = 0; i < vLines.size(); i++) {
		j = 1;
		do {
			TTF_SizeText(font, vLines[i].substr(0, j++).c_str(), &w, &h);
		} while(w < x - box.x && j <= vLines[i].size());
		if(i > 0) last += vLines[i - 1].size();
		if(y >= (box.y + (i * h)) && y <= (box.y + ((i + 1) * h))) {
			TTF_SizeText(font, vLines[i].substr(0, last + j - 1 + (i > 0 ? 1: 0)).c_str(), &w, NULL);
			TTF_SizeText(font, vLines[i].substr(0, last + j - 2 + (i > 0 ? 1: 0)).c_str(), &h, NULL);
			if(x < box.x + (w - ((w - h) / 2))) return last + j - 2 + (i > 0 ? 1: 0);  //this stuff should probably be floats
			else return last + j - 1 + (i > 0 ? 1: 0);
		}
	}
	return 0;
}

void SDLTextBox::doHighlight() {
	int last = 0;
	SDL_Rect dst, dst2;
	dst.x = 0;
	dst.y = 0;
	dst.w = 0;
	dst.h = 0;
	dst2.x = 0;
	dst2.y = 0;
	dst2.w = 0;
	dst2.h = 0;
	SDL_Surface *highlightSurface = 0; 
	int w = 0, h = 0;

	int start = 0, stop = 0;
	bool startFound = false, done = false;
	if(highlight.start < highlight.stop) {
		start = highlight.start;
		stop = highlight.stop;
	} else {
		start = highlight.stop;
		stop = highlight.start;
	}
	for(int i = 0; i < vLines.size(); i++) {
		if(!done) {
			if(startFound) {
				if(stop - last > vLines[i].size()) {
					TTF_SizeText(font, vLines[i].c_str(), &w, &h);
					dst.x = 0;
					dst.h = h;
					dst.w = w;
					dst.y = i * h;
					dst2.h = dst.h;
					dst2.w = dst.w;
					highlightSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, dst.w, dst.h, 32, 0, 0, 0, 0);
					SDL_SetAlpha(highlightSurface, SDL_SRCALPHA, 128);
					SDL_FillRect(highlightSurface, &dst2, 0x0000ff);
					apply_surface(box.x + dst.x, box.y + dst.y, highlightSurface, screen);
				} else {
					TTF_SizeText(font, vLines[i].substr(0, stop - last).c_str(), &w, &h);
					dst.x = 0;
					dst.h = h;
					dst.w = w;
					dst.y = i * h;
					dst2.h = dst.h;
					dst2.w = dst.w;
					highlightSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, dst.w, dst.h, 32, 0, 0, 0, 0);
					SDL_SetAlpha(highlightSurface, SDL_SRCALPHA, 128);
					SDL_FillRect(highlightSurface, &dst2, 0x0000ff);
					apply_surface(box.x + dst.x, box.y + dst.y, highlightSurface, screen);
					done = true;
				}
			} else if(start < vLines[i].size() + last && start > last) {
				startFound = true;
				if(stop - last > vLines[i].size()) {
					TTF_SizeText(font, vLines[i].substr(0, start - last).c_str(), &w, &h);
					dst.x = w;
					dst.h = h;
					TTF_SizeText(font, vLines[i].substr(start - last, vLines[i].size() - (start - last)).c_str(), &w, &h);
					dst.w = w;
					dst.y = i * h;
					dst2.h = dst.h;
					dst2.w = dst.w;
					highlightSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, dst.w, dst.h, 32, 0, 0, 0, 0);
					SDL_SetAlpha(highlightSurface, SDL_SRCALPHA, 128);
					SDL_FillRect(highlightSurface, &dst2, 0x0000ff);
					apply_surface(box.x + dst.x, box.y + dst.y, highlightSurface, screen);
				} else {
					TTF_SizeText(font, vLines[i].substr(0, start - last).c_str(), &w, &h);
					dst.x = w;
					dst.h = h;
					TTF_SizeText(font, vLines[i].substr(0, stop - last).c_str(), &w, &h);
					dst.w = w - dst.x;
					dst.y = i * h;
					dst2.h = dst.h;
					dst2.w = dst.w;
					highlightSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, dst.w, dst.h, 32, 0, 0, 0, 0);
					SDL_SetAlpha(highlightSurface, SDL_SRCALPHA, 128);
					SDL_FillRect(highlightSurface, &dst2, 0x0000ff);
					apply_surface(box.x + dst.x, box.y + dst.y, highlightSurface, screen);
					done = true;
				}
			}
			last += vLines[i].size();
		}
	}
	SDL_FreeSurface(highlightSurface);
}

void SDLTextBox::popupMenuAction(int num) {
	int x = 0, y = 0;
	string temp;
	switch(num) {
	case POPUP_CUT:
		if(highlight.start != highlight.stop) {
			if(highlight.start > highlight.stop) {
				x = highlight.stop;
				y = highlight.start;
			} else {
				x = highlight.start;
				y = highlight.stop;
			}
			if(str.substr(x, y - x).size() > 0) pClipboard->setData(str.substr(x, y - x));
			str.erase(x, y - x);
			caret.caretLoc = x;
			highlight.start = 0;
			highlight.stop = 0;
		}
		break;
	case POPUP_COPY:
		if(highlight.start != highlight.stop) {
			if(highlight.start > highlight.stop) {
				x = highlight.stop;
				y = highlight.start;
			} else {
				x = highlight.start;
				y = highlight.stop;
			}
			if(str.substr(x, y - x).size() > 0) pClipboard->setData(str.substr(x, y - x));
		}
		break;
	case POPUP_PASTE:
		if(pClipboard->getData().size() > 0) {
			if(highlight.start == highlight.stop) {
				temp = pClipboard->getData();
				if(temp.size() > 0) {
					if(str.size() + temp.size() > max_len) {
						x = max_len - str.size();
						temp.erase(x, temp.size() - x);
					}
					str.insert(caret.caretLoc, temp);
					caret.caretLoc += temp.size();
				}
			} else {
				if(highlight.start > highlight.stop) {
					x = highlight.stop;
					y = highlight.start;
				} else {
					x = highlight.start;
					y = highlight.stop;
				}
				temp = str.substr(x, y - x);
				str.erase(x, y - x);
				caret.caretLoc = y;
				caret.caretLoc -= temp.size();
				temp = pClipboard->getData();
				if(str.size() + temp.size() > max_len) {
					x = max_len - str.size();
					temp.erase(x, temp.size() - x);
				}
				str.insert(caret.caretLoc, temp);
				highlight.start = 0;
				highlight.stop = 0;
				caret.caretLoc += temp.size();
			}
		}
		break;
	case POPUP_SELECTALL:
		highlight.start = 1; //should be 0, fix when I go through and make 0 an acceptable index for highlighting
		highlight.stop = str.size();
		highlight.active = true;
		break;
	case POPUP_DELETE:
		if(highlight.start != highlight.stop) {
			if(highlight.start > highlight.stop) {
				x = highlight.stop;
				y = highlight.start;
			} else {
				x = highlight.start;
				y = highlight.stop;
			}
			str.erase(x, y - x);
			caret.caretLoc = x;
			highlight.start = 0;
			highlight.stop = 0;
		}
		break;
	}
}

void SDLTextBox::setFocus(bool state) {
	m_hasFocus = state;
}

bool SDLTextBox::hasFocus() { return m_hasFocus; }

bool SDLTextBox::popupActive() { return pPopupMenu->isVisible(); }

void SDLTextBox::setManager(LOK2WindowManager *manager) { pManager = manager; }

Uint32 _toggleCaret(Uint32 interval, void *oTextBox) {
	return ((SDLTextBox*)oTextBox)->toggleCaret(interval, oTextBox);
}
